﻿
#if DEBUG_GRAPHICS_ENABLED

using System;
using System.Collections.Generic;
using System.Diagnostics;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SunXNA.RainbowXNA;
using NeedsMoreNinja.EventManager;
using NeedsMoreNinja;

namespace SunXNA.DebugGraphics
{
    enum Type
    {
        Box = 0,

        NumberOf,
    }

    class CManager : IEventListener<SFillWorld>, IEventListener<SLoadContent>, IEventListener<SStep>
    {
        #region Public Types
        #endregion

        #region Private Types

        private struct SGraphic
        {
            public CRainbowXNA.CRenderInstance m_renderInstance;
            public double m_deathTime;
            public bool m_bInfinite;
        }

        #endregion

        #region Private Member Variables

        private Dictionary<UInt32, SGraphic> m_3DObjects;
        private CRainbowXNA.RenderObjectHandleType[] m_renderHandles;
        private double m_lastGameTime;

        #endregion

        #region Protected Member Variables
        #endregion

        #region Puplic Member Properties
        #endregion

        #region Public Member Functions

        public CManager()
        {
            m_renderHandles = new CRainbowXNA.RenderObjectHandleType[(int)Type.NumberOf];
            m_3DObjects = new Dictionary<uint, SGraphic>();

            CEventManager<SFillWorld>.AddListener(this);
            CEventManager<SLoadContent>.AddListener(this);
            CEventManager<SStep>.AddListener(this);
        }

        public void Add3DObject(UInt32 UID, Type type, Color colour, Matrix m4Transform, float lifeTime)
        {
            SGraphic newGraphic = new SGraphic();
            newGraphic.m_bInfinite = lifeTime < 0.0f;
            newGraphic.m_deathTime = m_lastGameTime + (double)lifeTime;
            newGraphic.m_renderInstance = Singleton<CRainbowXNA>.Instance.CreateRenderInstance(m_renderHandles[(int)type]);
            newGraphic.m_renderInstance.World = m4Transform;
            newGraphic.m_renderInstance.Material.Diffuse = colour.ToVector4();

            m_3DObjects[UID] = newGraphic;
        }

        public void Add3DObject(UInt32 UID, Type type, Color colour, Vector3 v3Pos, Vector3 v3Direction, Vector3 v3Scale, float lifeTime)
        {
            SGraphic newGraphic = new SGraphic();
            newGraphic.m_bInfinite = lifeTime < 0.0f;
            newGraphic.m_deathTime = m_lastGameTime + (double)lifeTime;
            newGraphic.m_renderInstance = Singleton<CRainbowXNA>.Instance.CreateRenderInstance(m_renderHandles[(int)type]);
            newGraphic.m_renderInstance.CreateWorld( v3Pos, v3Direction, v3Scale );
            newGraphic.m_renderInstance.Material.Diffuse = colour.ToVector4();

            m_3DObjects[UID] = newGraphic;
        }

        void IEventListener<SFillWorld>.Handle(SFillWorld e)
        {
            foreach (KeyValuePair<UInt32,SGraphic> graphicPair in m_3DObjects)
            {
                Singleton<CRainbowXNA>.Instance.AddPotentialVisibleObject(graphicPair.Value.m_renderInstance);
            }
        }

        void IEventListener<SLoadContent>.Handle(SLoadContent e)
        {
            VertexPositionColor[][] shapes = new VertexPositionColor[(int)Type.NumberOf][];
            PrimitiveType[] primitiveTypes = new PrimitiveType[(int)Type.NumberOf];

            #region Box
            {
                shapes[(int)Type.Box] = new VertexPositionColor[36]
                {
                    //
                    //  Front
                    //
                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, 0.5f ), Color.Red ),

                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, 0.5f ), Color.Red ),

                    //
                    // Back
                    //
                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, -0.5f ), Color.Red ),

                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, -0.5f ), Color.Red ),

                    //
                    //  Left
                    //
                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, 0.5f ), Color.Red ),

                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, 0.5f ), Color.Red ),

                    //
                    //  Right
                    //
                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, -0.5f ), Color.Red ),

                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, -0.5f ), Color.Red ),

                    //
                    //  Top
                    //
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, -0.5f ), Color.Red ),

                    new VertexPositionColor( new Vector3( -0.5f, 0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, 0.5f, 0.5f ), Color.Red ),

                    //
                    //  Bottom
                    //
                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, -0.5f ), Color.Red ),

                    new VertexPositionColor( new Vector3( 0.5f, -0.5f, 0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, -0.5f ), Color.Red ),
                    new VertexPositionColor( new Vector3( -0.5f, -0.5f, 0.5f ), Color.Red ),
                };

                primitiveTypes[(int)Type.Box] = PrimitiveType.TriangleList;
            }
            #endregion

            for (int i = 0; i < (int)Type.NumberOf; ++i)
            {
                m_renderHandles[i] = Singleton<CRainbowXNA>.Instance.CreateObject(shapes[i], primitiveTypes[i]);
            }
        }

        void IEventListener<SStep>.Handle(SStep e)
        {
            m_lastGameTime = e.gameTime.TotalGameTime.TotalSeconds;

            List<UInt32> deadIds = new List<UInt32>();

            foreach (KeyValuePair<UInt32, SGraphic> graphicPair in m_3DObjects)
            {
                if (graphicPair.Value.m_deathTime < m_lastGameTime && !graphicPair.Value.m_bInfinite)
                {
                    deadIds.Add(graphicPair.Key);
                }
            }

            foreach (UInt32 key in deadIds)
            {
                m_3DObjects.Remove(key);
            }
        }

        #endregion

        #region Protected Member Functions
        #endregion

        #region Private Member Functions
        #endregion
    }
}

#endif